﻿#nullable enable
using System.Collections.ObjectModel;
using System.Diagnostics;
using ymk_camera_surveillance.CaptureCamera;
using ymk_camera_surveillance.Database.DBModels;
using ymk_camera_surveillance.Views.CameraViews;

namespace ymk_camera_surveillance.Models
{
    public class AllCamera
    {
        public ObservableCollection<ObsCamera> Cameras { get; set; } = new ObservableCollection<ObsCamera>();

        private Thread? _flush_cameras_status = null;
        CancellationTokenSource cts = new CancellationTokenSource();

        private readonly Object CamerasLock = new Object();

        public AllCamera()
        {
            LoadAllCamera();
            StartFlushCamerasStatusThread();
        }

        private void StartFlushCamerasStatusThread()
        {
            _flush_cameras_status = new Thread(FlushCameras);
            _flush_cameras_status.Start(cts.Token);
        }

        ~AllCamera()
        {
            cts.Cancel();
            if (_flush_cameras_status != null)
            {
                _flush_cameras_status.Join();
            }
            cts.Dispose();
        }

        private void FlushCameras(object? obj)
        {

            if (obj is null)
            {
                return;
            }
            CancellationToken ct = (CancellationToken)obj;
            while (true)
            {
                try
                {
                    if (ct.IsCancellationRequested)
                    {
                        return;
                    }
                    lock (CamerasLock)
                    {
                        foreach (ObsCamera camera in Cameras)
                        {
                            var cap = CapManager.Instance.GetOrAddCapRtsp(camera.RtspUrl);
                            camera.State = cap.GetState();
                        }
                    }
                    Thread.Sleep(100);
                }
                catch (Exception e)
                {
                    Debug.WriteLine("FlushCameras Exception" + e.ToString());
                }
            }
        }

        private void LoadAllCamera()
        {
            Cameras.Clear();
            lock (CamerasLock)
            {
                foreach (ObsCamera camera in DBCamera.ToObs(DBCamera.Get(null)))
                {
                    Cameras.Add(camera);
                }
            }
        }

        public void AddCameraWithLock(ObsCamera camera)
        {
            lock (CamerasLock)
            {
                Cameras.Add(camera);
                var res = DBCamera.Save(DBCamera.FromObs(new List<ObsCamera> { camera }));
                if (res < 1)
                {
                    throw new Exception("create camera fail");
                }
                LoadAllCamera();
            }
        }

        public void DelCameraWithLock(int camera_id)
        {
            lock (CamerasLock)
            {
                var camera = Cameras.Single(c => c.Id == camera_id);
                Cameras.Remove(camera);
                var res = DBCamera.Delete(new List<int> { camera_id });
                if (res < 1)
                {
                    throw new Exception("delete camera fail");
                }
                LoadAllCamera();
            }
        }

    }
}
